#pragma once

#include <iostream>
#include <vector>
#include <queue>

////懒汉模式、启动快需要才请求资源

struct ThreadData
{
    pthread_t tid;
    std::string name;
};

template <class T>
class ThreadPool
{
    void lock()
    {
        pthread_mutex_lock(&mutex_);
    }

    void unLock()
    {
        pthread_mutex_unlock(&mutex_);
    }

    void wakeUp()
    {
        pthread_cond_signal(&cond_);
    }

    void threadSleep()
    {
        pthread_cond_wait(&cond_, &mutex_);
    }

    static const int defaultnum = 4;

private:
    ThreadPool(int num = defaultnum)
        : threads(num)
    {
        pthread_mutex_init(&mutex_, nullptr);
        pthread_cond_init(&cond_, nullptr);
    }

    ~ThreadPool()
    {
        pthread_mutex_destroy(&mutex_);
        pthread_cond_destroy(&cond_);
    }
    ThreadPool(const ThreadPool<T>& tp) = delete;
    ThreadPool<T>& operator=(const ThreadPool<T>& tp) = delete;

public:
    static ThreadPool<T>* getInstance()
    {
        if (tp_ == nullptr)
        {
            pthread_mutex_lock(&lock_);
            if (tp_ == nullptr)
            {
                std::cout << "log: singleton create done first!" << std::endl;
                tp_ = new ThreadPool<T>();
            }
            pthread_mutex_unlock(&lock_);
        }
        return tp_;
    }

    bool isEmpty()
    {
        return tasks.size() == 0;
    }

    static void *handlerTask(void *args)
    {
        ThreadPool<T> *tp = static_cast<ThreadPool<T> *>(args);
        std::string name = tp->getThreadName(pthread_self());

        while (true)
        {
            tp->lock();
            while (tp->isEmpty())
            {
                tp->threadSleep();
            }
            T tmp = tp->pop();
            tp->unLock();
            tmp();
        }
    }

    std::string getThreadName(const pthread_t &tid)
    {
        for (int i = 0; i < threads.size(); i++)
        {
            if (tid == threads[i].tid)
                return threads[i].name;
        }
        return "";
    }

    void strart()
    {
        for (int i = 0; i < threads.size(); i++)
        {
            threads[i].name = "thread--" + std::to_string(i);

            pthread_create(&(threads[i].tid), nullptr, handlerTask, this);
        }
    }

    void push(const T &t)
    {
        lock();
        tasks.push(t);
        wakeUp();
        unLock();
    }

    T pop()
    {
        T tmp = tasks.front();
        tasks.pop();
        return tmp;
    }

private:
    std::vector<ThreadData> threads;
    std::queue<T> tasks;

    pthread_mutex_t mutex_;
    pthread_cond_t cond_;

    static ThreadPool<T> *tp_; // 懒汉模式、启动快需要才请求资源
    static pthread_mutex_t lock_;
};

template <class T>
ThreadPool<T> *ThreadPool<T>::tp_ = nullptr;

template <class T>
pthread_mutex_t ThreadPool<T>::lock_ = PTHREAD_MUTEX_INITIALIZER;
